#include "h265rtpenc.h"
#include "udpsend.h"
typedef struct inputdata_t{
	uint32_t bufpos;
	uint32_t nextbufpos;
	uint8_t *inbuffer;
	int32_t inputdatasize;
}inputdata_t;

static int geth265nal(h265_rtpenc_ctx_t *h265_rtpenc_ctx, inputdata_t * pinputdata){
	int nalsize;
	int nalutype;
	int findnextframe = 0;
	int findstartcode = 0;
	if (pinputdata->inputdatasize < 4)
	{
		return -1;
	}
	pinputdata->nextbufpos += 4;
	pinputdata->inputdatasize -= 4;
	while (pinputdata->inputdatasize > 4)
	{
		if (pinputdata->inbuffer[pinputdata->nextbufpos] == 0)
		if (pinputdata->inbuffer[pinputdata->nextbufpos + 1] == 0)
		if (pinputdata->inbuffer[pinputdata->nextbufpos + 2] == 0)
		if (pinputdata->inbuffer[pinputdata->nextbufpos + 3] == 1)
		{
			if ((pinputdata->inbuffer[pinputdata->nextbufpos + 4] & 0x7E) >> 1 == 32 )
			{
				h265_rtpenc_ctx->hasvpsspspps = 1;
				findnextframe = 1;
			}
			nalutype = (pinputdata->inbuffer[pinputdata->nextbufpos + 4] & 0x7E) >> 1;
			if ((nalutype>15 && nalutype<22) || (nalutype>=0 && nalutype<10))
			{
				if (h265_rtpenc_ctx->hasvpsspspps)
				{
					h265_rtpenc_ctx->hasvpsspspps = 0;
				}
				else{
					findnextframe = 1;

				}
			}
			findstartcode = 1;
			break;
		}
		if (pinputdata->inbuffer[pinputdata->nextbufpos] == 0)
		if (pinputdata->inbuffer[pinputdata->nextbufpos + 1] == 0)
		if (pinputdata->inbuffer[pinputdata->nextbufpos + 2] == 1){
			findstartcode = 1;
			break;
		}
		pinputdata->nextbufpos++;
		pinputdata->inputdatasize--;
	}
	if (!findstartcode)
	{
		pinputdata->nextbufpos += pinputdata->inputdatasize;
		pinputdata->inputdatasize = 0;
	}

	h265_rtpenc_ctx->nalu_buffer = pinputdata->inbuffer + pinputdata->bufpos;
	h265_rtpenc_ctx->nalu_size = pinputdata->nextbufpos - pinputdata->bufpos;
	pinputdata->bufpos = pinputdata->nextbufpos;
	if (findnextframe)
	{
		h265_rtpenc_ctx->blastnal = 1;
	}
	else{
		h265_rtpenc_ctx->blastnal = 0;
	}

	return findstartcode;
}

static int getnalstartpos( inputdata_t * inputdata){
	while (1)
	{
		if (inputdata->inbuffer[inputdata->bufpos] == 0)
		if (inputdata->inbuffer[inputdata->bufpos+1] == 0)
		if (inputdata->inbuffer[inputdata->bufpos+2] == 0)
		if (inputdata->inbuffer[inputdata->bufpos+3] == 1)
		{
			//find vps ,break
			if ((inputdata->inbuffer[inputdata->bufpos + 4] & 0x7E) >> 1 == 32){
				break;
			}
		}
		inputdata->bufpos++;
		inputdata->inputdatasize--;
	}
	inputdata->nextbufpos = inputdata->bufpos ;
	return 0;
}
//return,NULL
unsigned char *getbuffer(int file_size){
	unsigned char *buf = (unsigned char*)malloc(file_size);
	return buf;
}
int getfilesize(FILE * fd){
	int len = 0;
	fseek(fd, 0, SEEK_END);
	len = ftell(fd);
	fseek(fd, 0, SEEK_SET);
	return len;
}
int main(){
	h265_rtpenc_ctx_t h265_rtpenc_ctx = { 0 };
	inputdata_t inputdata = { 0 };
	udpsend_ctx_t udpsend_ctx = { 0 };
	int nalucount = 0;
	int ret;
	FILE * h265file_fd = fopen("1.h265","rb");

	inputdata.inputdatasize = getfilesize(h265file_fd);
	if (inputdata.inputdatasize<= 0)
	{
		return -1;
	}
	inputdata.inbuffer = (uint8_t *)malloc(inputdata.inputdatasize);
	if (inputdata.inbuffer == NULL)
	{
		return -1;
	}
	ret = fread(inputdata.inbuffer, 1, inputdata.inputdatasize, h265file_fd);
	if (ret != inputdata.inputdatasize)
	{
		return -1;
	}

	h265_rtpenc_init(&h265_rtpenc_ctx);
	getnalstartpos(&inputdata);
	udpsend_init(&udpsend_ctx);
	h265_rtpenc_ctx.privatedata = &udpsend_ctx;
	while (1)
	{
		ret = geth265nal(&h265_rtpenc_ctx, &inputdata);
		if (ret < 0)
		{
			printf("have no data\n");
			break;
		}
		printf("process nalucount =%d\n", nalucount);
		nalucount++;
		ret = h265_rtpenc(&h265_rtpenc_ctx);
		if (ret < 0)
		{
			printf("h265_rtpenc failed\n");
			break;
		}
	}
	printf("h265_rtpenc task end!\n");
	h265_rtpenc_uninit(&h265_rtpenc_ctx);
	udpsend_close(&udpsend_ctx);
	return 0;
}